package com.miniapp.core.utils;



import com.miniapp.common.config.PaicFtiWebDriverConfig;
import com.miniapp.common.gen.domain.PaicFtiAccount;
import com.miniapp.common.gen.domain.PaicFtiAccountExample;
import com.miniapp.common.gen.mapper.PaicFtiAccountMapper;
import com.miniapp.common.utils.StringUtils;
import com.yl.ddddocr.OCREngine;
import com.yl.ddddocr.utils.ImageUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 平安货运险登录
 */
@Component
public class PaicLoginUtil {


    private Logger logger = LoggerFactory.getLogger(PaicLoginUtil.class);

    @Autowired
    private PaicFtiWebDriverConfig paicFtiWebDriverConfig;

    @Autowired
    private PaicFtiChromeDriverUtils paicFtiChromeDriverUtils;

    @Autowired
    private PaicFtiAccountMapper paicFtiAccountMapper;

    //上一次操作的时间
    private Map<String,Long> userNamePperation = new HashMap<>();

    private static OCREngine engine = OCREngine.instance();

    /**
     * 获取投保页面的ChromeDriver
     * @param userName
     * @param password
     * @param requestId
     * @return
     */
    public ChromeDriver getInsurePageChromeDriver(String userName,String password,String requestId){
        //1.获取登录的ChromeDriver
        ChromeDriver loginChromeDriver = this.login(userName, password, requestId);

        //2、进入到投保页面
        String currentUrl = loginChromeDriver.getCurrentUrl();
        logger.info("获取完登录后的ChromeDriver，当前页面为："+currentUrl);
        if("https://cargo.pa18.com/cargo/#/display-board".equals(currentUrl)){
            ChromeDriver chromeDriver = this.gotoInsurePage(loginChromeDriver);
            return chromeDriver;
        }else if("https://cargo.pa18.com/cargo/#/quotation".equals(currentUrl)){
            logger.info("开始点击投保服务");
            ThreadUtils.threadSleep(500);
            WebElement toubao = loginChromeDriver.findElement(By.xpath("//*[@id=\"quotation-table\"]/div/div[2]/table/tbody/tr/td[1]/div/div/div/button[1]"));
            toubao.click();
            logger.info("点击投保服务完成");
            ThreadUtils.threadSleep(500);
            return loginChromeDriver;
        } else if(currentUrl.contains("https://cargo.pa18.com/cargo/#/document-info?quotationNo=")){
            logger.info("当前页面在投保页面，不用进行操作");
            return loginChromeDriver;
        }else {
            //都不是，重新悬停投保服务
            ChromeDriver chromeDriver = this.gotoInsurePage(loginChromeDriver);
            return chromeDriver;
        }

    }

    /**
     * 平安货运险登录
     * @return ChromeDriver 返回一个已经登录成功的 ChromeDriver
     */
    public ChromeDriver login(String userName,String password,String requestId){
        ThreadUtils.threadSleep(1000);

        String loggerInfo = "请求唯一id为："+requestId+",平安货运险登录,账号:"+userName+",";
        PaicFtiAccountExample paicFtiAccountExample = new PaicFtiAccountExample();
        paicFtiAccountExample.createCriteria().andUserNameEqualTo(userName).andPasswordEqualTo(password);
        List<PaicFtiAccount> paicFtiAccountList = paicFtiAccountMapper.selectByExample(paicFtiAccountExample);
        if(CollectionUtils.isEmpty(paicFtiAccountList)){
            logger.info("平安货运险登录，账号：{}，密码：{}，账号或密码错误",userName,password);
            throw new RuntimeException("账号或密码错误");
        }
        //1、判断对应账号的浏览器是否打开
        ChromeDriver chromeDriver = PaicFtiChromeDriverUtils.paicFtiChromeAccountMap.get(userName);
        if(chromeDriver == null){
            logger.info(loggerInfo+"打开谷歌浏览器");
            //浏览器未打开，打开浏览器
            chromeDriver = paicFtiChromeDriverUtils.openChrome();
            userNamePperation.put(userName,System.currentTimeMillis());
            //存入对应的map中
            PaicFtiChromeDriverUtils.paicFtiChromeAccountMap.put(userName,chromeDriver);
        }
        logger.info(loggerInfo+"谷歌浏览器已经打开,不需要重新打开");


        //2、判断页面是否在登录界面，不在登录界面说明登录成功
        //当前的url地址
        String currentUrl = "";
        try {
            //上一次的操作时间
            Long beforOperationTime = userNamePperation.get(userName);
            long currentTimeMillis = System.currentTimeMillis();
            long intervalTime = currentTimeMillis - beforOperationTime;
            //超过两个小时没操作刷新页面
            if(intervalTime > 1000 * 60 * 60 *2){
                chromeDriver.navigate().refresh();
                ThreadUtils.threadSleep(5000);
            }
            userNamePperation.put(userName,currentTimeMillis);

            ThreadUtils.threadSleep(100);
             currentUrl = chromeDriver.getCurrentUrl();
        }catch (Exception e){
            //报错 说明浏览器已经关闭 需要重新初始化浏览器
            logger.info(loggerInfo+"获取输入账号input报错，重新初始化打开浏览器");
            paicFtiChromeDriverUtils.closeChromeByUserName(userName);
            return login(userName,password,requestId);
        }
        if(!"https://cargo.pa18.com/cargo/#/login".equals(currentUrl)){
            logger.info(loggerInfo+"不是登录的url,认定已经登录成功,url地址为:{}",currentUrl);
            //不存在说明没在登录界面
            return chromeDriver;
        }
        logger.info(loggerInfo+"开始登录");

        //3、在登录界面
        //输入账号

        WebElement accountInput = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[1]/div/div/div/input");
        accountInput.clear();
        if(userName.contains("_DOWNLOAD_POLICY")){
            //_DOWNLOAD_POLICY后缀是下载电子保单账号
            accountInput.sendKeys(userName.replace("_DOWNLOAD_POLICY",""));
        }else {
            accountInput.sendKeys(userName);
        }
        logger.info(loggerInfo+"账号输入完成");
        //输入密码
        WebElement passwordInput = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[2]/div/div[1]/div/input");
        passwordInput.clear();
        passwordInput.sendKeys(password);
        logger.info(loggerInfo+"密码输入完成");

        //识别验证码
        logger.info(loggerInfo+"开始输入验证码");
        String verificationCodeStr = "";
        for (int i = 0; i < 100; i++) {
            logger.info(loggerInfo+"第"+(i+1)+"次识别验证码");
            //获取验证码
            WebElement verificationCodeElement = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[3]/div/img");
            //刷新验证码
            verificationCodeElement.click();
            ThreadUtils.threadSleep(800);
            //获取刷新的验证码
            verificationCodeElement = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[3]/div/img");
            String verificationCodeBase64 = verificationCodeElement.getAttribute("src");
            logger.info(loggerInfo+"识别到验证码base64为："+verificationCodeBase64);
            verificationCodeBase64 = verificationCodeBase64.replace("data:image/jpg;base64,","");
            BufferedImage bufferedImage = ImageUtils.toImage(verificationCodeBase64);
            verificationCodeStr = engine.recognize(bufferedImage);
            logger.info(loggerInfo+"识别到的验证码是："+verificationCodeStr);
            //识别的验证码等于4位
            if(StringUtils.isNotBlank(verificationCodeStr) && verificationCodeStr.length() == 4){
                logger.info(loggerInfo+"识别到验证码为4位跳出循环");
                break;
            }
        }
        if(StringUtils.isBlank(verificationCodeStr) || verificationCodeStr.length() != 4){
            logger.info(loggerInfo+"刷新100次验证码识别不到4位，抛出异常");
            throw new RuntimeException("平安货运险："+userName+"，登录失败，请联系管理员,错误代码：001");
        }

        //输入验证码
        WebElement verificationCodeInput = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[3]/div/div/div/input");
        verificationCodeInput.clear();
        verificationCodeInput.sendKeys(verificationCodeStr);
        logger.info(loggerInfo+"输入验证码");


        //点击登录
        WebElement loginButton = chromeDriver.findElementByXPath("//*[@id=\"mainSection\"]/div/div[1]/div/div[2]/div/div[2]/form/div[4]/button");
        loginButton.click();
        logger.info(loggerInfo+"点击登录");

        ThreadUtils.threadSleep(2000);
        String loginAfterUrl = chromeDriver.getCurrentUrl();
        //登录成功返回 chromeDriver
        if("https://cargo.pa18.com/cargo/#/display-board".equals(loginAfterUrl)){
            return chromeDriver;
        }
        return login(userName,password,requestId);
    }

    /**
     * 登录成功后去投保页面
     * @return
     */
    private ChromeDriver gotoInsurePage(ChromeDriver chromeDriver){
        //当前的url地址
        String currentUrl = chromeDriver.getCurrentUrl();
        //登录成功的url：https://cargo.pa18.com/cargo/#/display-board

        //1、关掉弹窗
        ThreadUtils.threadSleep(500);
        List<WebElement> posterList = chromeDriver.findElementsByXPath("/html/body/div[4]/div/i");
        if(CollectionUtils.isNotEmpty(posterList)){
            WebElement posterWebElement = posterList.get(0);
            posterWebElement.click();
            logger.info("关掉海报弹窗");
        }
        ThreadUtils.threadSleep(500);
        //2、关提示
        List<WebElement> promptList = chromeDriver.findElementsByXPath("//*[@id=\"app\"]/div/div[1]/div/div/div[2]/div[7]/div/div/button[1]");
        if(CollectionUtils.isNotEmpty(promptList)){
            WebElement promptWebElement = promptList.get(0);
            promptWebElement.click();
            logger.info("关掉提示弹窗");
        }
        ThreadUtils.threadSleep(500);
        // 3、定位到要悬停的元素(投保服务)
        WebElement element = chromeDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[1]/div/div/div[2]/div[2]"));
        // 使用Actions类来执行鼠标悬停
        Actions actions = new Actions(chromeDriver);
        actions.moveToElement(element).perform();
        ThreadUtils.threadSleep(500);
        logger.info("悬浮到（投保服务）");
        //4、点击在线投保
        WebElement zaixiantoubao = chromeDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[1]/div/div/div[2]/div[2]/div/div[1]"));
        zaixiantoubao.click();
        ThreadUtils.threadSleep(1000);
        logger.info("点击在线投保");

        //5、点击投保
        WebElement toubao = chromeDriver.findElement(By.xpath("//*[@id=\"quotation-table\"]/div/div[2]/table/tbody/tr/td[1]/div/div/div/button[1]"));
        toubao.click();
        ThreadUtils.threadSleep(800);
        logger.info("点击投保");
        return chromeDriver;
    }










}
